package com.douqu.game.core.entity;


import com.alibaba.fastjson.JSONObject;
import com.bean.core.buffer.ByteBuffer;
import com.bean.core.util.HttpJsonUtils;
import com.bean.core.util.TimeUtils;
import com.bean.core.util.Utils;
import com.douqu.game.core.config.GuideConfig;
import com.douqu.game.core.config.MailConfig;
import com.douqu.game.core.config.PlayerLvConfig;
import com.douqu.game.core.config.VipConfig;
import com.douqu.game.core.config.card.CardConfig;
import com.douqu.game.core.config.common.GoodsData;
import com.douqu.game.core.config.goods.PropConfig;
import com.douqu.game.core.config.sprite.MasterConfig;
import com.douqu.game.core.config.sprite.SoldierConfig;
import com.douqu.game.core.controller.PlayerController;
import com.douqu.game.core.database.model.PlayerModel;
import com.douqu.game.core.e.E_GuideType;
import com.douqu.game.core.e.E_LegionChinaType;
import com.douqu.game.core.e.E_MailModelType;
import com.douqu.game.core.e.E_MailSenderType;
import com.douqu.game.core.entity.common.TwoTuple;
import com.douqu.game.core.entity.db.*;
import com.douqu.game.core.entity.ext.*;
import com.douqu.game.core.entity.ext.data.boon.*;
import com.douqu.game.core.entity.ext.data.card.CardData;
import com.douqu.game.core.entity.ext.data.challenge.*;
import com.douqu.game.core.entity.ext.data.major.CollectData;
import com.douqu.game.core.entity.ext.data.major.TalentData;
import com.douqu.game.core.entity.ext.data.mall.MallData;
import com.douqu.game.core.entity.world.WorldOfficialBean;
import com.douqu.game.core.entity.world.map.SpritePlayerBean;
import com.douqu.game.core.entity.world.map.WorldMapData;
import com.douqu.game.core.factory.*;
import com.douqu.game.core.i.IGetExtraAddAttribute;
import com.douqu.game.core.protobuf.SGCommonProto;
import com.douqu.game.core.util.CoreUtils;
import com.douqu.game.core.util.LogUtils;
import com.douqu.game.core.util.SendUtils;

import java.text.MessageFormat;
import java.util.*;

/**
 * Created by bean on 2017/7/14.
 */
public class Player extends GameObject {

    //头像
    public String avatar;

    //营地
    public int camp;

    //主将
    public int master;

    //是否被封号
    public boolean isDel;

    /**
     * 总战力
     */
    public int fc;

    /** RMB冲值的对应币 */
    public int money;

    //uuid
    private int uid;

    //账号
    private String account;

    //配置id
    private String deviceId;

    //channel 对应的channel 每个玩家都有他唯一对应的channel
    public Integer channel;

    //创建时间
    private Date createTime;

    //上次登录时间
    private Date lastLoginTime;

    //上次登出时间
    private Date lastLogoutTime;

    private Map<String, ExtInfo> extInfos;


    /**
     * 成长盒子
     */
    private LvDB lvDB;

    //vip等级
    private int vipLevel;

    //vip经验
    private int vipExp;

    private ChangeGoods changeGoods;


    /**
     * 无敌状态(只在开发版本有用)
     */
    public boolean invincible;

    /**
     * 锁住
     */
    public boolean lock;

    /**
     * 加密KEY
     */
    private String encodeKey = "";

    /**绑定的手机号*/
    private String mobile ="";

//    /**
//     * 是否处于单人战场
//     */
//    private boolean isSingleWorldMap;

    //检测引导条件
    List<SGCommonProto.E_GUIDE_CHECK> guideList ;

    /**
     * @param playerModel
     */
    public Player(PlayerModel playerModel)
    {
        definition();

        initExtInfo();

        load(playerModel);
    }

    /**
     * 注册时用
     */
    public Player()
    {
        definition();

        initExtInfo();
    }



    private void initExtInfo()
    {
        addExtInfo(new BagInfo(this));
        addExtInfo(new ChallengeInfo(this));
        addExtInfo(new BoonInfo(this));
        addExtInfo(new TaskInfo(this));
        addExtInfo(new SettingInfo(this));
        addExtInfo(new MailInfo(this));
        addExtInfo(new MajorInfo(this));
    }


    private void definition()
    {
        lvDB = new LvDB(this);

        changeGoods = new ChangeGoods();

        extInfos = new HashMap<>();
    }

    public void clearAll()
    {
        lvDB.reset();
        vipLevel = 0;
        vipExp = 0;

        extInfos.clear();

        initExtInfo();

        init();
    }

    public void init()
    {
        if(camp == 0)
            camp = SGCommonProto.E_CAMP_TYPE.CAMP_TYPE_BRIGHT_VALUE;

        if(master == 0)
        {
            List<MasterConfig> masterConfigs = DataFactory.getInstance().getDataList(DataFactory.MASTER_KEY);
            for(MasterConfig masterConfig : masterConfigs)
            {
                if(masterConfig.camp == camp)
                {
                    master = masterConfig.id;
                    break;
                }
            }
        }

        getExtInfo(BagInfo.class).init();

        for(ExtInfo extInfo : extInfos.values())
        {
            if(extInfo instanceof BagInfo)
                continue;

            extInfo.init();
        }

        updateFC();
    }

    public void checkInit()
    {
        for(ExtInfo extInfo : extInfos.values())
        {
            extInfo.checkInit();
        }
    }

    public void reset()
    {
        for(ExtInfo extInfo : extInfos.values())
        {
            extInfo.reset();
        }

        updateFC();
    }

    public void checkReset()
    {
        for(ExtInfo extInfo : extInfos.values())
        {
            extInfo.checkReset();
        }
    }


    private void load(PlayerModel playerModel)
    {
        if(playerModel == null)
            return;

        this.id = playerModel.getId();
        this.objectIndex = playerModel.getObjectIndex();
        this.avatar = playerModel.getAvatar();
        this.uid = playerModel.getUid();
        this.name = playerModel.getName();
        this.account = playerModel.getAccount();
        this.deviceId = playerModel.getDeviceId();
        this.channel = playerModel.getChannel();
        this.camp = playerModel.getCamp();
        this.master = playerModel.getMaster();
        this.fc = playerModel.getFc();
        this.money = playerModel.getMoney();
        this.createTime = playerModel.getCreateTime();
        this.lastLoginTime = playerModel.getLastLoginTime();
        this.lastLogoutTime = playerModel.getLastLogoutTime();
        this.vipExp = playerModel.getVipExp();
        this.vipLevel = playerModel.getVipLevel();
        this.mobile = playerModel.getMobile();
        this.isDel = playerModel.getIsDel();

        if(lvDB == null) lvDB = new LvDB(this);
        lvDB.lv = playerModel.getLevel();
        lvDB.lv = lvDB.lv < 1 ? 1 : lvDB.lv;
        lvDB.exp = playerModel.getExp();
        PlayerLvConfig curConfig = DataFactory.getInstance().getGameObject(DataFactory.PLAYER_LV_KEY, lvDB.lv);
        lvDB.exp = lvDB.exp < curConfig.totalExp ? curConfig.totalExp : lvDB.exp;
        PlayerLvConfig nextConfig = DataFactory.getInstance().getGameObject(DataFactory.PLAYER_LV_KEY, lvDB.lv+1);
        if(nextConfig != null)
        {
            lvDB.exp = lvDB.exp >= nextConfig.totalExp ? curConfig.totalExp : lvDB.exp;
        }

        if(DataFactory.getInstance().getGameObject(DataFactory.MASTER_KEY, this.master) == null){
            List<MasterConfig> masterConfigs = DataFactory.getInstance().getDataList(DataFactory.MASTER_KEY);
            for(MasterConfig masterConfig : masterConfigs)
            {
                if(masterConfig.camp == this.camp)
                {
                    this.master = masterConfig.id;
                    break;
                }
            }
        }
        //这里加载数据库的数据
        byte[] byteData = playerModel.getBagInfo();
        if(byteData != null)
        {
            getExtInfo(BagInfo.class).loadFrom(new ByteBuffer(byteData));
        }

        byteData = playerModel.getMajorInfo();
        if(byteData != null)
        {
            getExtInfo(MajorInfo.class).loadFrom(new ByteBuffer(byteData));
        }

        byteData = playerModel.getChallengeInfo();
        if(byteData != null)
        {
            getExtInfo(ChallengeInfo.class).loadFrom(new ByteBuffer(byteData));
        }

        byteData = playerModel.getBoonInfo();
        if(byteData != null)
        {
            getExtInfo(BoonInfo.class).loadFrom(new ByteBuffer(byteData));
        }

        byteData = playerModel.getTaskInfo();
        if(byteData != null)
        {
            getExtInfo(TaskInfo.class).loadFrom(new ByteBuffer(byteData));
        }

        byteData = playerModel.getSettingInfo();
        if(byteData != null)
        {
            getExtInfo(SettingInfo.class).loadFrom(new ByteBuffer(byteData));
        }

        byteData = playerModel.getMailInfo();
        if(byteData != null)
        {
            getExtInfo(MailInfo.class).loadFrom(new ByteBuffer(byteData));
        }


        checkInit();

        checkReset();

        if (CoreUtils.isFunctionUnLock(FunctionFactory.UNLOCK_LEGION_CHAIN, this))
        {
            getCardData().calculateAll();
        }

        updateFC();
    }


    public PlayerModel save()
    {
        PlayerModel playerModel = new PlayerModel();
        playerModel.setId(id);
        playerModel.setName(name);
        playerModel.setObjectIndex(objectIndex);
        playerModel.setAvatar(avatar);
        playerModel.setCamp(camp);
        playerModel.setLevel(lvDB.lv);
        playerModel.setExp(lvDB.exp);
        playerModel.setVipLevel(vipLevel);
        playerModel.setVipExp(vipExp);
        playerModel.setMaster(master);
        playerModel.setMoney(money);
        playerModel.setUid(uid);
        playerModel.setFc(fc);
        playerModel.setIsDel(isDel);
        playerModel.setLastLoginTime(lastLoginTime);
        playerModel.setLastLogoutTime(lastLogoutTime);
        playerModel.setCreateTime(createTime);

        //复制给PlayerModel
        ByteBuffer buffer = new ByteBuffer();
        getExtInfo(BagInfo.class).writeTo(buffer);
        playerModel.setBagInfo(buffer.getBytes());


        buffer = new ByteBuffer();
        getExtInfo(ChallengeInfo.class).writeTo(buffer);
        playerModel.setChallengeInfo(buffer.getBytes());

        buffer = new ByteBuffer();
        getExtInfo(TaskInfo.class).writeTo(buffer);
        playerModel.setTaskInfo(buffer.getBytes());

        buffer = new ByteBuffer();
        getExtInfo(BoonInfo.class).writeTo(buffer);
        playerModel.setBoonInfo(buffer.getBytes());

        buffer = new ByteBuffer();
        getExtInfo(SettingInfo.class).writeTo(buffer);
        playerModel.setSettingInfo(buffer.getBytes());

        buffer = new ByteBuffer();
        getExtInfo(MailInfo.class).writeTo(buffer);
        playerModel.setMailInfo(buffer.getBytes());

        buffer = new ByteBuffer();
        getExtInfo(MajorInfo.class).writeTo(buffer);
        playerModel.setMajorInfo(buffer.getBytes());

        return playerModel;
    }


//    public String getChannel()
//    {
//        if(StringUtils.isNullOrEmpty(account))
//            return "";
//
//        return account.indexOf("_") == -1 ? account : account.substring(0, account.indexOf("_"));
//    }


    public void createKey()
    {
        this.encodeKey = CoreUtils.createUUID(8).toUpperCase();
    }



    public void cacheRedPoint(SGCommonProto.E_RED_POINT_TYPE e_red_point_type){
        if(!changeGoods.getRedPointTypes().contains(e_red_point_type)){
            changeGoods.getRedPointTypes().add(e_red_point_type);
        }
    }

    public void sendReadPoint(PlayerController playerController){
        if(changeGoods.getRedPointTypes().size() == 0)
            return;

        SendUtils.sendRedPointRemind(playerController, changeGoods.getRedPointTypes());
        changeGoods.getRedPointTypes().clear();
    }

    public void sendLegionChain(PlayerController playerController){
        if(changeGoods.getLegionChainCacheMap().size() == 0)
            return;

//        Iterator<Map.Entry<Integer, Integer>> iterator = changeGoods.getLegionChainCacheMap().entrySet().iterator();
//        while (iterator.hasNext()){
//            Map.Entry<Integer, Integer> next = iterator.next();
//            SGPlayerProto.S2C_LegionChainUnlock.Builder response =  SGPlayerProto.S2C_LegionChainUnlock.newBuilder();
//            response.setLegionChainId(next.getKey());
//            response.setIndex(next.getValue());
//            LogUtils.debug("连锁解锁:" + response.toString());
//            playerController.sendMsg(SGMainProto.E_MSG_ID.MsgID_Player_LegionChainUnlock_VALUE, response.build().toByteArray());
//        }

        changeGoods.getLegionChainCacheMap().clear();
    }

    /**
     *  检测添加物品条件的红点
     * @param type
     * @param id
     */
    public void checkRedPointRemind(SGCommonProto.E_GOODS_TYPE type, int id)
    {
        for(ExtInfo extInfo : extInfos.values())
        {
            extInfo.checkRedPointRemindAddGoods(type, id);
        }
    }

    /**
     * 检测所有条件的红点,一般在登录304返回
     * @return
     */
    public List<SGCommonProto.E_RED_POINT_TYPE> getAllRedPointTypes(long currentTime){
        List<SGCommonProto.E_RED_POINT_TYPE> list = new ArrayList<>();
        List<SGCommonProto.E_RED_POINT_TYPE> temp = null;
        list.addAll(changeGoods.getRedPointTypes());
        for(ExtInfo extInfo : extInfos.values())
        {
            temp = extInfo.checkRedPointRemindAllCondition(currentTime);
            if(temp != null){
                list.addAll(temp);
            }
        }

        changeGoods.getRedPointTypes().clear();
        return list;
    }


    public boolean isNewDay()
    {
        if(lastLogoutTime != null)
        {
            return !TimeUtils.isToday(lastLogoutTime);
        }

        return true;
    }

    public BagInfo getBagInfo()
    {
        return getExtInfo(BagInfo.class);
    }


    public RechargeRecordData getRechargeRecordData()
    {
        BoonInfo boonInfo =  getExtInfo(BoonInfo.class);
        return boonInfo.getRechargeRecordData();
    }

    public CollectData getCollectData(){
        return getMajorInfo().getCollectData();
    }
    //todo 天赋
    public TalentData getTalentData(){
        return getMajorInfo().getTalentData();
    }

    public ArenaData getArenaData()
    {
        ChallengeInfo challengeInfo = getExtInfo(ChallengeInfo.class);
        return challengeInfo.getArenaData();
    }
    public BossData getBossData()
    {
        ChallengeInfo challengeInfo = getExtInfo(ChallengeInfo.class);
        return challengeInfo.getBossData();
    }

    public ExpeditionData getExpeditionData()
    {
        ChallengeInfo challengeInfo =  getExtInfo(ChallengeInfo.class);
        return challengeInfo.getExpeditionData();
    }

    public OfficialRankData getOfficialData()
    {
        ChallengeInfo challengeInfo = getExtInfo(ChallengeInfo.class);
        return challengeInfo.getOfficialData();
    }

    public InstanceData getInstanceData()
    {
        ChallengeInfo challengeInfo = getExtInfo(ChallengeInfo.class);
        return challengeInfo.getInstanceData();
    }


    public HeroTempleData getHeroTempleData()
    {
        ChallengeInfo challengeInfo = getExtInfo(ChallengeInfo.class);
        return challengeInfo.getHeroTempleData();
    }

    public AltarData getAltarData()
    {
        BoonInfo boonInfo = getExtInfo(BoonInfo.class);
        return boonInfo.getAltarData();
    }

    public MajorInfo getMajorInfo()
    {
        return  getExtInfo(MajorInfo.class);
    }

    public LotteryData getLotteryData()
    {
        BoonInfo boonInfo = getExtInfo(BoonInfo.class);
        return boonInfo.getLotteryData();
    }

    public RechargeRecordData getRechargeData()
    {
        BoonInfo boonInfo = getExtInfo(BoonInfo.class);
        return boonInfo.getRechargeRecordData();
    }

    public BonusData getBonusData()
    {
        BoonInfo boonInfo = getExtInfo(BoonInfo.class);
        return boonInfo.getBonusData();
    }

    public ShareData getShareData(){
        BoonInfo boonInfo = getExtInfo(BoonInfo.class);
        return boonInfo.getShareData();
    }

    public CardData getCardData(){
        BagInfo bagInfo = getExtInfo(BagInfo.class);
        return bagInfo.getCardData();
    }

    public CampBattleData getCampBattleData()
    {
        ChallengeInfo challengeInfo = getExtInfo(ChallengeInfo.class);
        return challengeInfo.getCampBattleData();
    }

    public MallData getMallData() {
        BoonInfo boonInfo = getExtInfo(BoonInfo.class);
        return boonInfo.getMallData();
    }


    public OnlineRewardData getOnlineData() {
        BoonInfo boonInfo = getExtInfo(BoonInfo.class);
        return boonInfo.getOnlineRewardData();
    }

    public SevenDayData getSevenDayData() {
        BoonInfo boonInfo = getExtInfo(BoonInfo.class);
       return boonInfo.getSevenDayData();
    }



    public WorldMapTaskData getWorldMapTaskData(){
        return getExtInfo(ChallengeInfo.class).getWorldMapTaskData();
    }

    /**
     * 这里的参数 bool 纯粹是为了方法的重载
     * @param bool
     */
    public void updateFC(boolean bool)
    {
        //修改战斗力
        int beforeFC = fc;

        int afterFC = updateFC();

        if(beforeFC != afterFC)
        {
            addChangeGoods(SGCommonProto.E_GOODS_TYPE.GOODS_TYPE_OTHER, SGCommonProto.E_GOODS_OTHER_ID.GOODS_OTHER_ID_FC_VALUE, afterFC - beforeFC, afterFC, true);
        }
    }

    /**
     * 更新总战力
     * 玩家当前使用的组卡内所有单位的战斗力 + 主将战斗力
     * @return
     */
    public int updateFC()
    {
        BagInfo bagInfo = getExtInfo(BagInfo.class);

        int cardFc = 0;
        int masterFc = 0;
        List<CardDB> cards = bagInfo.getCardData().getBattleCardList();
        for(CardDB card : cards)
        {
            cardFc += card.updateFC();
        }

        MasterConfig masterConfigObj = DataFactory.getInstance().getGameObject(DataFactory.MASTER_KEY, master);
        if(masterConfigObj == null)
        {
            masterConfigObj = (MasterConfig) DataFactory.getInstance().getDataList(DataFactory.MASTER_KEY).get(0);
            master = masterConfigObj.id;
        }
        masterFc += masterConfigObj.getFC(getLv(), new IGetExtraAddAttribute() {
            @Override
            public int getAttributeValue(int attId) {
                //添加天赋所加值
                int upTalentValue = getTalentData().masterTalentAttribute(attId);
                return upTalentValue+getMasterExtraAddAttributes(attId);
            }
        });

        this.fc = cardFc + masterFc;
        
        // 检测任务是否完成
        getExtInfo(TaskInfo.class).check(TaskFactory.TASK_TARAGET_BATTLE_FC, fc);

        //升级检测开服活动是否完成
        getSevenDayData().checkAllRewardState(SevenDayFactory.EVENT_TYPE_3,fc);

        WorldMapData worldMapData = WorldInfoFactory.getInstance().getWorldMapData();
        SpritePlayerBean spritePlayerBean = worldMapData.getPlayerActionBean(objectIndex);
        if(spritePlayerBean != null)
            spritePlayerBean.updateBaseInfo(this);

        return cardFc + masterFc;
    }



    /**
     * 添加钻石(元宝)
     * @param value
     */
    public void addMoney(int value)
    {
        if(value == 0)
            return;

        BagInfo bagInfo = getExtInfo(BagInfo.class);
        bagInfo.addAsset(ConfigFactory.ASSET_MONEY_KEY, value);
    }


    /**
     * 增加vip经验
     * @return 增加经验后的vip等级
     */
    public int addVipExp(int vipExp){
        this.vipExp += vipExp;
        int vipLvBefore = vipLevel;
        List<VipConfig> vipConfigs = DataFactory.getInstance().getDataList(DataFactory.VIP_KEY);
        int size = vipConfigs.size();
        for(int i = 1; i< size; i++){
            if(this.vipExp < vipConfigs.get(i).needRecharge){
                this.vipLevel = vipConfigs.get(i - 1).id;
                break;
            }
        }
        if(vipLvBefore != vipLevel){//vip level up
            vipLvUp(vipLvBefore);

            addChangeGoods(SGCommonProto.E_GOODS_TYPE.GOODS_TYPE_OTHER, SGCommonProto.E_GOODS_OTHER_ID.GOODS_OTHER_ID_VIP_LV_VALUE, vipLevel-vipLvBefore, vipLevel, true);
        }
        addChangeGoods(SGCommonProto.E_GOODS_TYPE.GOODS_TYPE_OTHER, SGCommonProto.E_GOODS_OTHER_ID.GOODS_OTHER_ID_VIP_EXP_VALUE, vipExp, this.vipExp, true);
        return vipLevel;
    }

    /**
     * vip升级了
     */
    private void vipLvUp(int vipLvBefore) {
        //获取上一个vip等级的配置表
        VipConfig lastConfig = DataFactory.getInstance().getGameObject(DataFactory.VIP_KEY,vipLvBefore);
        //获取当前vip等级的配置表
        VipConfig currentConfig = DataFactory.getInstance().getGameObject(DataFactory.VIP_KEY,vipLevel);
        //祭坛补上免费差x
        for(Map.Entry<Integer,SingleBoonData> entry : getAltarData().altarMap.entrySet()){
            entry.getValue().addFreeCount(currentConfig.altarFreeTimesMap.get(entry.getKey()) - lastConfig.altarFreeTimesMap.get(entry.getKey()));
        }
        //修改竞技场
        getArenaData().addTodayTotalChallengeTimee(currentConfig.arenaFreeTimes - lastConfig.arenaFreeTimes);
        //修改每日采集次数
        getCollectData().addMaxCollectTimes(currentConfig.dailyCollectTimes - lastConfig.dailyCollectTimes);
        //修改boss每日挑战次数
        getBossData().addTodayTotalChallengeTimes(currentConfig.bossChallengeTimes - lastConfig.bossChallengeTimes);
        //修改远征最大次数
        getExpeditionData().addTodayTotalResetTimes(currentConfig.expeditionFreeTimes - lastConfig.expeditionFreeTimes);
        //升级检测开服活动是否完成
        getSevenDayData().checkAllRewardState(SevenDayFactory.EVENT_TYPE_6,vipLevel);
    }


    public TwoTuple<Boolean, Boolean> addExp(int value)
    {
        //最大等级
        int maxLv = DataFactory.getInstance().MAX_PLAYER_LV;
        //根据当前等级获取最大经验值
        PlayerLvConfig playerLvConfig =  DataFactory.getInstance().getGameObject(DataFactory.PLAYER_LV_KEY,maxLv);
        int maxExp = playerLvConfig.totalExp;
        if(maxExp > 0 && getExp()  < maxExp){
            int beforeLevel = getLv();
            lvDB.addExp(value);

            int afterLevel = getLv();
            if(beforeLevel != afterLevel){//升级了
                getCardData().calculateLegionChinaResult(E_LegionChinaType.ALL);
                int result = updateFC();
                addChangeGoods(SGCommonProto.E_GOODS_TYPE.GOODS_TYPE_OTHER, SGCommonProto.E_GOODS_OTHER_ID.GOODS_OTHER_ID_FC_VALUE, result, fc, true);

                boolean has = levelUp(beforeLevel);

                SettingInfo settingInfo = getExtInfo(SettingInfo.class);
                settingInfo.setLastLvUpTime(DataFactory.currentTime);

                TaskInfo taskInfo = getExtInfo(TaskInfo.class);
            	// 检测任务是否完成
                taskInfo.check(TaskFactory.TASK_TARAGET_MAINUPLV, afterLevel);

                //主将升级后检测任务下发
                taskInfo.addNewTaskByLevelUp();
                //升级检测是否开启在线奖励倒计时
                getOnlineData().clearOnlineReward((byte) 0);
                //升级检测开服活动是否完成
                getSevenDayData().checkAllRewardState(SevenDayFactory.EVENT_TYPE_2,afterLevel);
                return new TwoTuple<>(true, has);
            } else {
                return new TwoTuple<>(false, false);
            }
        }

        return new TwoTuple<>(false, false);
    }

    /**
     * 玩家升级
     * @param beforeLevel
     * @return
     */
    private boolean levelUp(int beforeLevel)
    {
        SettingInfo settingInfo = getExtInfo(SettingInfo.class);
        boolean has = settingInfo.levelUpToNewUnlockSkill(beforeLevel);
        if(settingInfo.levelUpToNewUnlockSkill(beforeLevel)){
//            changeGoods.getRedPointTypes().add(SGCommonProto.E_RED_POINT_TYPE.RED_POINT_TYPE_MASTER);
        }

        BagInfo bagInfo = getExtInfo(BagInfo.class);
        if(bagInfo.getCardData().checkCorps()){
            changeGoods.getRedPointTypes().add(SGCommonProto.E_RED_POINT_TYPE.RED_POINT_TYPE_LEGION);
        }
        MailInfo mailInfo =  getExtInfo(MailInfo.class);
        //玩家升级检测 英雄奖励
        List<PlayerLvConfig> list = DataFactory.getInstance().getPlayerLvSectionList(beforeLevel, getLv());

        MailConfig mailConfig = DataFactory.getInstance().getGameObject(DataFactory.MAIL_MODEL_KEY, E_MailModelType.LEVEL_REWARD.getCode());
        if(mailConfig != null)
        {
            String title = mailConfig.title;
            String content = mailConfig.content;
            for(PlayerLvConfig playerLvConfig : list)
            {
                if(playerLvConfig.reward != null)
                {
                    for(GoodsData goodsData : playerLvConfig.reward)
                    {
                        //背包添加英雄
                        bagInfo.addGoods(goodsData,true);
                        if(goodsData.type == SGCommonProto.E_GOODS_TYPE.GOODS_TYPE_CARDS_VALUE)
                        {
                            CardConfig card = DataFactory.getInstance().getGameObject(DataFactory.CARD_KEY, goodsData.id);
                            mailInfo.addMail(SGCommonProto.E_MAIL_TYPE.MAIL_TYPE_SYSTEM_VALUE,title,MessageFormat.format(content, card.name),E_MailSenderType.MAIL_TYPE_RECEIVER.getCode(),getObjectIndex(),null,DataFactory.currentTime);

                            CardDB toBattleCard = bagInfo.getCardData().getMaxFCSleepCard();
                            if(toBattleCard != null)
                            {
                                bagInfo.getCardData().changeCardBattleStatus(toBattleCard, true);
                                changeGoods.addGoods(SGCommonProto.E_GOODS_TYPE.GOODS_TYPE_OTHER, SGCommonProto.E_GOODS_OTHER_ID.GOODS_OTHER_ID_BATTLE_CARD_VALUE, toBattleCard.id, 1, "", 0, true);
                            }
                        }
                    }
                }
            }
        }
        //通知认证服务器等级改变
        toUpdateAuthServerLevelChange();
        return has;
    }

    private void toUpdateAuthServerLevelChange() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("channel", channel);
        jsonObject.put("account", getAccount());
        jsonObject.put("level", getLv());
        jsonObject.put("serverId", WorldInfoFactory.getInstance().getServerId());


        try {
            if(CoreUtils.isNullOrEmpty(WorldInfoFactory.getInstance().getAuthServerHost()))
                return;

            JSONObject result = HttpJsonUtils.httpPost(WorldInfoFactory.getInstance().getAuthServerHost() + HttpFactory.PLAYER_UPDATE_RECORD2, jsonObject);
            if(result == null){
                LogUtils.error("请求认证服务器验证名称合法性出错：");
                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取资源数量
     * @param key
     * @return
     */
    public int getAsset(int key)
    {
        BagInfo bagInfo = getExtInfo(BagInfo.class);
        return bagInfo.getAsset(key);
    }


    public int getLv()
    {
        return lvDB.lv;
    }

    public int getExp()
    {
        return lvDB.exp;
    }



    public void addExtInfo(ExtInfo extInfo)
    {
        if(extInfos == null)
            extInfos = new HashMap<String, ExtInfo>();

        extInfos.put(extInfo.getName(), extInfo);
    }



    /**
     * 获取主将额外增加的属性值(主将培养和吃药)
     * @return
     */
    public int getMasterExtraAddAttributes(int attrId){
        int attribute = 0;
        SettingInfo info = getExtInfo(SettingInfo.class);
        Integer masterTrain = info.getMasterAttributes().get(attrId);
        attribute += (masterTrain == null ? 0  : masterTrain);
//        LogUtils.debug("增加属性值 key:" + attrId + "， 值：" + attribute );

        PropConfig propConfig;
        for(Map.Entry<Integer, Integer> entry : info.getMasterLiquidMap().entrySet())
        {
            propConfig = DataFactory.getInstance().getGameObject(DataFactory.PROP_KEY, entry.getKey());
            if(propConfig != null &&
                    propConfig.type == ConstantFactory.PROP_TYPE_LIQUID &&
                    propConfig.liquidData[0].type == attrId){
                attribute +=(propConfig.liquidData[0].id * entry.getValue());
            }
        }

        return attribute;
    }

    /**
     * 获取活动大厅显示列表
     * @return
     */
    public List<SGCommonProto.ActivityHallColumn> initActivityHallDay(SGCommonProto.E_ACTIVITY_HALL_TYPE type){
        List<SGCommonProto.ActivityHallColumn> list = new ArrayList<>();
        return list;
    }

    public ChangeGoods getChangeGoods() {
        return changeGoods;
    }

    public void addChangeGoods(SGCommonProto.E_GOODS_TYPE goodsType, int id, int change, int curValue, Object... hide)
    {
        changeGoods.addGoods(goodsType, id, change, curValue, null, 0, hide);
    }

    public void addChangeTimeGoods(SGCommonProto.E_GOODS_TYPE goodsType, int id, int change, int curValue,
                                   String uniqueId, long endTime, Object... hide)
    {
        changeGoods.addGoods(goodsType, id, change, curValue,uniqueId, endTime, hide);
    }

    public <T extends ExtInfo> T getExtInfo(Class<T> cls)
    {
        return (T) extInfos.get(cls.getSimpleName());
    }

    public PlayerLvConfig getPlayerLvConfig(){
        return DataFactory.getInstance().getGameObject(DataFactory.PLAYER_LV_KEY, getLv());
    }



    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public String getNoChannelAccount()
    {
        if(Utils.isNullOrEmpty(account))
            return "";

        return account.substring(account.indexOf("_")+1);
    }

    public String getNameLv()
    {
        return name + "(Lv" + lvDB.lv + ")";
    }


    public Date getLastLoginTime() {
        return lastLoginTime;
    }

    public void setLastLoginTime(Date lastLoginTime) {
        this.lastLoginTime = lastLoginTime;
    }

    public Date getLastLogoutTime() {
        return lastLogoutTime;
    }

    public void setLastLogoutTime(Date lastLogoutTime) {
        this.lastLogoutTime = lastLogoutTime;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getDeviceId() {
        return deviceId;
    }

    public void setDeviceId(String deviceId) {
        this.deviceId = deviceId;
    }

    public int getVipLevel() {
        return vipLevel;
    }

    public void setVipLevel(int vipLevel) {
        this.vipLevel = vipLevel;
    }

    public int getVipExp() {
        return vipExp;
    }

    public void setVipExp(int vipExp) {
        this.vipExp = vipExp;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public String getEncodeKey() {
        return encodeKey;
    }

    public String getMobile() {
        return mobile == null ? "":mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public ChallengeInfo getChallengeInfo(){
        return getExtInfo(ChallengeInfo.class);
    }

    public WorldMapKillData getWorldMapKillData(){
        return getWorldMapTaskData().getKillData();
    }

    public List<CardDB> getWorldMapCardList()
    {
        List<CardDB> list = getWorldMapTaskData().getBattleCardList();
        if(list.isEmpty())
            list = getCardData().getBattleCardList();

        return list;
    }

    public List<CardDB> getCampCardList()
    {
        List<CardDB> list = getCampBattleData().getBattleCardList();
        if(list.isEmpty())
            list = getCardData().getBattleCardList();

        return list;
    }


    /**
     * 检测引导相关
     * @return
     */
    public  List<SGCommonProto.E_GUIDE_CHECK>  checkAllGuide(){
        if (guideList == null){
            guideList =new ArrayList<>();
            checkGuide();
            return guideList;
        }
        return guideList;
    }

    private void checkGuide() {
        //用到的类型
        List<Integer> guideType = new ArrayList<>();
        List<GuideConfig> list = DataFactory.getInstance().getDataList(DataFactory.GUIDE_TYPE);
        for (GuideConfig config : list) {
            if (!guideType.contains(config.groupPass)) {
                guideType.add(config.groupPass);
            }
        }
        LogUtils.info("已用到的引导类型 ->"+guideType);
        //是否有改类型的引导
        boolean isCheck;
        //英雄相关 -根据玩家拥有的英雄列表逐个判断
        for (CardDB cardDB : getCardData().getCardMap().values()) {

            //英雄是否升星
            isCheck = guideType.contains(E_GuideType.IS_HERO_STAR.getCode());
            if (isCheck && cardDB.star > 0 && !guideList.contains(SGCommonProto.E_GUIDE_CHECK.IS_HERO_STAR)) {
                guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_HERO_STAR);
            }
            //英雄是否升级
            isCheck = guideType.contains(E_GuideType.IS_HERO_LV.getCode());
            if (isCheck && cardDB.getLv() > 1 && !guideList.contains(SGCommonProto.E_GUIDE_CHECK.IS_HERO_LV)) {
                guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_HERO_LV);
            }
            //装备
            isCheck = guideType.contains(E_GuideType.IS_EQUIP_COMPONSE.getCode()) ||
                    guideType.contains(E_GuideType.IS_EQUIP_STRENG.getCode());
            if (isCheck) {
                for (EquipDB equipDB : cardDB.getEquipMap().values()) {
                    //装备是否合成
                    if (equipDB.upCount > 0 && !guideList.contains(SGCommonProto.E_GUIDE_CHECK.IS_EQUIP_COMPONSE)) {
                        guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_EQUIP_COMPONSE);
                    }
                    //装备是否强化
                    if (equipDB.getLv() > 1 && !guideList.contains(SGCommonProto.E_GUIDE_CHECK.IS_EQUIP_STRENG)) {
                        guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_EQUIP_STRENG);
                    }
                }
            }
            //饰品
            isCheck = guideType.contains(E_GuideType.IS_HERO_ORNAMENTS_ACTIVATE.getCode()) ||
                    guideType.contains(E_GuideType.IS_HERO_ORNAMENTS_LV.getCode());
            if (isCheck) {
                for (AccessoryDB accessoryDB : cardDB.getAccessoryMap().values()) {
                    if (accessoryDB.getLv() > 1 && !guideList.contains(SGCommonProto.E_GUIDE_CHECK.IS_HERO_ORNAMENTS_ACTIVATE)) {
                        guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_HERO_ORNAMENTS_ACTIVATE);
                    }
                    if (accessoryDB.upLv > 1 && !guideList.contains(SGCommonProto.E_GUIDE_CHECK.IS_HERO_ORNAMENTS_LV)) {
                        guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_HERO_ORNAMENTS_LV);
                    }
                }
            }
            //是否使用过药水  -根据使用的药水改变的属性Map判断
            isCheck = guideType.contains(E_GuideType.IS_HERO_USELIQUID.getCode());
            if (isCheck && cardDB.cardLiquidMap.size() != 0 && !guideList.contains(SGCommonProto.E_GUIDE_CHECK.IS_HERO_USELIQUID)) {
                guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_HERO_USELIQUID);
            }
        }
        //是否单抽 -根据玩家单抽抽取次数判断
        isCheck = guideType.contains(E_GuideType.IS_PUB_BUY_ONE.getCode());
        LotteryDB lotteryDB;
        if (isCheck) {
            lotteryDB = this.getLotteryData().getDiamondSingleDB();
            if(lotteryDB.currentNum > 0){
                guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_PUB_BUY_ONE);
            }
        }
        //是否10连抽 -根据玩家十连抽取次数判断
        isCheck = guideType.contains(E_GuideType.IS_PUB_BUY_TEN.getCode());
        if (isCheck) {
            lotteryDB = this.getLotteryData().getDiamondMuchDB();
            if(lotteryDB.currentNum > 0){
                guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_PUB_BUY_TEN);
            }
        }
        //主将是否培养 -根据使用的药水改变的属性Map判断
        isCheck = guideType.contains(E_GuideType.IS_MASTER_TRAIN.getCode());
        if (isCheck) {
            SettingInfo settingInfo = getExtInfo(SettingInfo.class);
            if (settingInfo.getMasterLiquidMap().size() != 0) {
                guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_MASTER_TRAIN);
            }
        }
        //官阶 -根据有无官阶判断
        isCheck = guideType.contains(E_GuideType.IS_OFFICIAL.getCode());
        if (isCheck) {
            WorldOfficialBean rankBean = WorldInfoFactory.getInstance().getWorldOfficialData()
                    .getRankInfoByObjectIndex(this);
            if (rankBean != null) {
                guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_OFFICIAL);
            }
        }
        //竞技场 -根据竞技胜利次数判断
        isCheck = guideType.contains(E_GuideType.IS_ARENA.getCode());
        if (isCheck && getArenaData().getTotalWinCount() > 0) {
            guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_ARENA);
        }

        //采集过 -根据采取物品次数判断
        isCheck = guideType.contains(E_GuideType.IS_MAJOR_COLLECT.getCode());
        boolean isMajor;
        if (isCheck) {
            isMajor = getMajorInfo().getCollectData().isMajor();
            if (isMajor) {
                guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_MAJOR_COLLECT);
            }
        }
        //炼制药水 -根据合成物品次数判断
        isCheck = guideType.contains(E_GuideType.IS_MAJOR_REFINING.getCode());
        if (isCheck) {
            isMajor = getMajorInfo().getRefiningData().isMajorRefining();
            if (isMajor) {
                guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_MAJOR_REFINING);
            }
        }
        //祭坛任意祭祀 -根据第一次献祭时间判断
        isCheck = guideType.contains(E_GuideType.IS_ALTAR.getCode());
        if (isCheck){
           for (SingleBoonData boonData:getAltarData().altarMap.values()){
               if (boonData.getFirstLotteryTime()!= 0){
                   guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_ALTAR);
                   break;
               }
           }
        }
        //召唤远征BOSS -根据最大通关次数和关卡判断
        isCheck = guideType.contains(E_GuideType.IS_BOSS.getCode());
        boolean isEnterBoss =  getExpeditionData().getMaxLevelNum() > 0 ||getExpeditionData().getLastLevelId()!= 0;
        if (isCheck && isEnterBoss){
            guideList.add(SGCommonProto.E_GUIDE_CHECK.IS_BOSS);
        }
        //todo 当前自动战斗开启状态[战斗系统的，拿不到]
        //todo 进入战场过 （目前获取不到是否进入过）
    }





    @Override
    public String toString() {
        return "Player{" +
                "camp=" + camp +
                ", money=" + money +
                ", lv=" + getLv() +
                "} " + super.toString();
    }




}
